feat: run the Spock-backed Instagram demo through Uhura#9
Conversation
Add stored video objects, private saves, multi-frame stories, whitespace-safe comments, and a richer relational seed; advance Uhura to the fully Spock-backed client.
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. WalkthroughThe PR standardizes Node.js 24 tooling, enables permissive runtime CORS, adds an Instagram Spock authority with seeded data, and introduces a supervised script for running Spock and Uhura together. ChangesUhura and Spock integration
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Runner as spock-uhura.sh
participant Spock as spock-cli
participant Uhura as uhura-cli
Runner->>Spock: Build and start Spock
Runner->>Spock: Wait for /~health
Runner->>Uhura: Start the Uhura editor
Runner->>Uhura: Wait for the editor URL
Runner->>Spock: Stop Spock when Uhura exits
Runner->>Uhura: Stop Uhura when Spock exits
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
examples/instagram-poc/app.spock (1)
148-159: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAdd
unique(post, position)tocarousel_slide.
storyenforcesunique(author, position)for exactly this "deterministic ordered sequence" need (line 90), butcarousel_slidedoesn't have the equivalentunique(post, position). Nothing writes carousel slides today, but the asymmetry with the sibling table is worth closing now while it's cheap.🔧 Proposed fix
table carousel_slide { key id: uuid = auto /// The carousel post this slide belongs to. post: post on delete cascade /// Slide order, 1-based. position: int /// The slide image stored in Spock's byte plane. file: storage_object /// Alt text for the slide. alt: text + unique (post, position) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/instagram-poc/app.spock` around lines 148 - 159, Add a composite uniqueness constraint on post and position to the carousel_slide table, matching the existing unique(author, position) pattern used by story. Keep the current fields and relationships unchanged.crates/spock-runtime/studio/.npmrc (1)
1-3: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winMove pnpm version-policy settings out of
.npmrc.manage-package-manager-versionsandpackage-manager-strict-versionare removed in pnpm 11, and.npmrcthere is limited to auth/registry settings. Put these inpnpm-workspace.yamlbefore bumping the pnpm pin.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/spock-runtime/studio/.npmrc` around lines 1 - 3, Remove manage-package-manager-versions and package-manager-strict-version from .npmrc, then add the equivalent pnpm version-policy settings to pnpm-workspace.yaml using its supported configuration keys before updating the pinned pnpm version. Keep engine-strict in .npmrc.examples/instagram/client/package.json (1)
5-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winEnforce the npm pin in the example setup
packageManagerhere is only metadata:examples/instagram/client/README.mdtells contributors to runnvm useandnpm install, and.npmrconly setsengine-strict=truefor Node. Add Corepack or adevEngines.packageManagercheck ifnpm@11.16.0is required.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/instagram/client/package.json` around lines 5 - 8, Update the examples/instagram/client setup to enforce the required npm@11.16.0 version rather than relying on the packageManager metadata; add an appropriate Corepack configuration or devEngines.packageManager check, and ensure the existing README npm install workflow triggers that validation.Source: MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/instagram-poc/app.spock`:
- Around line 415-800: Audit every file("./seed/...") reference in the seed
block, identify the asset missing from the examples/instagram-poc/seed
collection, and either add that asset or correct the reference to an existing
file. Preserve the intended media mapping for the associated story, post,
carousel slide, or profile field, especially the story declarations such as
lena_story and mira_story.
In `@uhura`:
- Line 1: Restore and check in the generated web Wasm artifacts under the Uhura
submodule, specifically uhura_wasm.js and uhura_wasm_bg.wasm expected by
scripts/spock-uhura.sh, or update the launcher’s preflight requirement if those
artifacts are intentionally no longer needed; ensure a clean checkout passes the
launcher preflight.
---
Nitpick comments:
In `@crates/spock-runtime/studio/.npmrc`:
- Around line 1-3: Remove manage-package-manager-versions and
package-manager-strict-version from .npmrc, then add the equivalent pnpm
version-policy settings to pnpm-workspace.yaml using its supported configuration
keys before updating the pinned pnpm version. Keep engine-strict in .npmrc.
In `@examples/instagram-poc/app.spock`:
- Around line 148-159: Add a composite uniqueness constraint on post and
position to the carousel_slide table, matching the existing unique(author,
position) pattern used by story. Keep the current fields and relationships
unchanged.
In `@examples/instagram/client/package.json`:
- Around line 5-8: Update the examples/instagram/client setup to enforce the
required npm@11.16.0 version rather than relying on the packageManager metadata;
add an appropriate Corepack configuration or devEngines.packageManager check,
and ensure the existing README npm install workflow triggers that validation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e1304f4b-31c0-4ba2-a0f2-fdfc3dbabd49
⛔ Files ignored due to path filters (40)
Cargo.lockis excluded by!**/*.lockcrates/spock-runtime/studio/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlexamples/instagram-poc/seed/avatar-ayla.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-june.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-kenji.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-lena.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-marco.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-mira.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-nils.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-priya.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/avatar-theo.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-ayla-ferry.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-june-lookbook.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-kenji-copper.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-lena-glaze.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-marco-baja-1.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-marco-baja-2.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-marco-baja-3.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-mira-ferry.mp4is excluded by!**/*.mp4examples/instagram-poc/seed/media-nils-aurora-poster.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-nils-aurora.mp4is excluded by!**/*.mp4examples/instagram-poc/seed/media-priya-starter.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-theo-court.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/media-theo-court.mp4is excluded by!**/*.mp4examples/instagram-poc/seed/thumb-lena-1.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-2.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-3.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-4.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-5.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-6.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-7.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-8.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-lena-9.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-mira-1.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-mira-2.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-mira-3.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-mira-4.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-mira-5.jpgis excluded by!**/*.jpgexamples/instagram-poc/seed/thumb-mira-6.jpgis excluded by!**/*.jpgexamples/instagram/client/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (16)
.github/workflows/npm.yml.nvmrcREADME.mdcrates/spock-runtime/Cargo.tomlcrates/spock-runtime/src/http.rscrates/spock-runtime/studio/.npmrccrates/spock-runtime/studio/README.mdcrates/spock-runtime/studio/package.jsoncrates/spock-runtime/tests/http.rsdocs/rfd/0020-distribution.mdexamples/instagram-poc/app.spockexamples/instagram/client/.npmrcexamples/instagram/client/README.mdexamples/instagram/client/package.jsonscripts/spock-uhura.shuhura
| seed { | ||
| // People use stable ids because the Play provider's actor header is Mira's | ||
| // UUID. Every person has a complete profile; no profile count is seeded. | ||
| mira = user { id: "10000000-0000-4000-8000-000000000001", | ||
| username: "mira.santos", display_name: "Mira Santos", | ||
| avatar: file("./seed/avatar-mira.jpg"), avatar_alt: "Mira Santos", | ||
| bio: "Food and travel photographer in Lisbon. Usually awake before the trams." } | ||
| lena = user { id: "10000000-0000-4000-8000-000000000002", | ||
| username: "lena.holt", display_name: "Lena Holt", | ||
| avatar: file("./seed/avatar-lena.jpg"), avatar_alt: "Lena Holt", | ||
| bio: "Ceramics and slow mornings. Small-batch studio work from Portland." } | ||
| marco = user { id: "10000000-0000-4000-8000-000000000003", | ||
| username: "marco.reyes", display_name: "Marco Reyes", | ||
| avatar: file("./seed/avatar-marco.jpg"), avatar_alt: "Marco Reyes", | ||
| bio: "Surf photographer, road-trip cook, and reluctant morning person." } | ||
| nils = user { id: "10000000-0000-4000-8000-000000000004", | ||
| username: "nils.bergman", display_name: "Nils Bergman", | ||
| avatar: file("./seed/avatar-nils.jpg"), avatar_alt: "Nils Bergman", | ||
| bio: "Night skies and northern water, filmed around Tromsø." } | ||
| priya = user { id: "10000000-0000-4000-8000-000000000005", | ||
| username: "priya.raman", display_name: "Priya Raman", | ||
| avatar: file("./seed/avatar-priya.jpg"), avatar_alt: "Priya Raman", | ||
| bio: "Bread notebook, tiny kitchen, stubborn sourdough starter." } | ||
| ayla = user { id: "10000000-0000-4000-8000-000000000006", | ||
| username: "ayla.demir", display_name: "Ayla Demir", | ||
| avatar: file("./seed/avatar-ayla.jpg"), avatar_alt: "Ayla Demir", | ||
| bio: "Istanbul by ferry. Architecture, tea, and ordinary light." } | ||
| june = user { id: "10000000-0000-4000-8000-000000000007", | ||
| username: "june.park", display_name: "June Park", | ||
| avatar: file("./seed/avatar-june.jpg"), avatar_alt: "June Park", | ||
| bio: "Natural-fiber clothes made in a very crowded studio." } | ||
| theo = user { id: "10000000-0000-4000-8000-000000000008", | ||
| username: "theo.okafor", display_name: "Theo Okafor", | ||
| avatar: file("./seed/avatar-theo.jpg"), avatar_alt: "Theo Okafor", | ||
| bio: "Murals, community courts, and an unreliable jump shot." } | ||
| kenji = user { id: "10000000-0000-4000-8000-000000000009", | ||
| username: "kenji.rides", display_name: "Kenji Tanaka", | ||
| avatar: file("./seed/avatar-kenji.jpg"), avatar_alt: "Kenji Tanaka", | ||
| bio: "Long climbs, quiet roads, and coffee at the turnaround." } | ||
|
|
||
| // Directed relationships: every Followers/Following count and list comes | ||
| // from these edges. Mira follows six people and has four followers. | ||
| follow { follower: mira, followed: lena } | ||
| follow { follower: mira, followed: marco } | ||
| follow { follower: mira, followed: priya } | ||
| follow { follower: mira, followed: ayla } | ||
| follow { follower: mira, followed: june } | ||
| follow { follower: mira, followed: kenji } | ||
| follow { follower: lena, followed: mira } | ||
| follow { follower: lena, followed: marco } | ||
| follow { follower: lena, followed: priya } | ||
| follow { follower: lena, followed: june } | ||
| follow { follower: lena, followed: theo } | ||
| follow { follower: marco, followed: lena } | ||
| follow { follower: marco, followed: nils } | ||
| follow { follower: marco, followed: ayla } | ||
| follow { follower: marco, followed: kenji } | ||
| follow { follower: nils, followed: lena } | ||
| follow { follower: nils, followed: marco } | ||
| follow { follower: nils, followed: theo } | ||
| follow { follower: priya, followed: mira } | ||
| follow { follower: priya, followed: lena } | ||
| follow { follower: priya, followed: ayla } | ||
| follow { follower: priya, followed: june } | ||
| follow { follower: ayla, followed: lena } | ||
| follow { follower: ayla, followed: priya } | ||
| follow { follower: ayla, followed: june } | ||
| follow { follower: june, followed: mira } | ||
| follow { follower: june, followed: lena } | ||
| follow { follower: june, followed: ayla } | ||
| follow { follower: june, followed: theo } | ||
| follow { follower: theo, followed: mira } | ||
| follow { follower: theo, followed: lena } | ||
| follow { follower: theo, followed: june } | ||
| follow { follower: kenji, followed: lena } | ||
| follow { follower: kenji, followed: marco } | ||
| follow { follower: kenji, followed: nils } | ||
| follow { follower: kenji, followed: priya } | ||
|
|
||
| // Twelve active frames across six tray authors. Mira, Lena, and Marco each | ||
| // carry a three-frame sequence so the story player exercises progress and | ||
| // next/previous navigation. Story-view rows below make Lena, Marco, and June | ||
| // unseen to Mira while Priya and Kenji are already seen. | ||
| mira_story = story { | ||
| id: "30000000-0000-4000-8000-000000000001", author: mira, position: 1, | ||
| media_file: file("./seed/thumb-mira-1.jpg"), | ||
| media_alt: "Pastéis de nata cooling on a marble counter", | ||
| caption: "Breakfast before the first tram", | ||
| published_at: "2026-07-13T15:10:00Z" } | ||
| mira_story_tram = story { | ||
| id: "30000000-0000-4000-8000-000000000008", author: mira, position: 2, | ||
| media_file: file("./seed/thumb-mira-2.jpg"), | ||
| media_alt: "Tram rails catching the first light in Lisbon", | ||
| caption: "Then the city wakes", | ||
| published_at: "2026-07-13T15:22:00Z" } | ||
| mira_story_market = story { | ||
| id: "30000000-0000-4000-8000-000000000009", author: mira, position: 3, | ||
| media_file: file("./seed/thumb-mira-3.jpg"), | ||
| media_alt: "Crates of citrus stacked at the morning market", | ||
| caption: "Saturday palette", | ||
| published_at: "2026-07-13T15:38:00Z" } | ||
| lena_story = story { | ||
| id: "30000000-0000-4000-8000-000000000002", author: lena, position: 1, | ||
| media_file: file("./seed/thumb-lena-7.jpg"), | ||
| media_alt: "Lena throwing a tall clay cylinder", | ||
| caption: "One pull, no edits", | ||
| published_at: "2026-07-13T14:55:00Z" } | ||
| lena_story_glazes = story { | ||
| id: "30000000-0000-4000-8000-000000000010", author: lena, position: 2, | ||
| media_file: file("./seed/thumb-lena-8.jpg"), | ||
| media_alt: "Rows of glaze buckets labelled by firing cone", | ||
| caption: "The unglamorous half of studio day", | ||
| published_at: "2026-07-13T15:08:00Z" } | ||
| lena_story_studio = story { | ||
| id: "30000000-0000-4000-8000-000000000011", author: lena, position: 3, | ||
| media_file: file("./seed/thumb-lena-9.jpg"), | ||
| media_alt: "Morning light crossing a clean ceramics workbench", | ||
| caption: "Reset for tomorrow", | ||
| published_at: "2026-07-13T15:24:00Z" } | ||
| marco_story = story { | ||
| id: "30000000-0000-4000-8000-000000000004", author: marco, position: 1, | ||
| media_file: file("./seed/media-marco-baja-2.jpg"), | ||
| media_alt: "Campfire on a bluff above the break", | ||
| caption: "Last night at camp", | ||
| published_at: "2026-07-13T14:40:00Z" } | ||
| marco_story_swell = story { | ||
| id: "30000000-0000-4000-8000-000000000012", author: marco, position: 2, | ||
| media_file: file("./seed/media-marco-baja-1.jpg"), | ||
| media_alt: "Long left-hand wave peeling along a desert point", | ||
| caption: "It finally arrived", | ||
| published_at: "2026-07-13T14:52:00Z" } | ||
| marco_story_dawn = story { | ||
| id: "30000000-0000-4000-8000-000000000013", author: marco, position: 3, | ||
| media_file: file("./seed/media-marco-baja-3.jpg"), | ||
| media_alt: "Surfboard fins silhouetted against a Baja sunrise", | ||
| caption: "Pack up before the wind", | ||
| published_at: "2026-07-13T15:04:00Z" } | ||
| priya_story = story { | ||
| id: "30000000-0000-4000-8000-000000000005", author: priya, position: 1, | ||
| media_file: file("./seed/media-priya-starter.jpg"), | ||
| media_alt: "Freshly sliced sourdough loaf", | ||
| caption: "Still warm", | ||
| published_at: "2026-07-13T14:20:00Z" } | ||
| june_story = story { | ||
| id: "30000000-0000-4000-8000-000000000006", author: june, position: 1, | ||
| media_file: file("./seed/media-june-lookbook.jpg"), | ||
| media_alt: "Linen garments arranged by shade", | ||
| caption: "Fitting day", | ||
| published_at: "2026-07-13T13:50:00Z" } | ||
| kenji_story = story { | ||
| id: "30000000-0000-4000-8000-000000000007", author: kenji, position: 1, | ||
| media_file: file("./seed/media-kenji-copper.jpg"), | ||
| media_alt: "Road bike at Copper Pass", | ||
| caption: "Worth the climb", | ||
| published_at: "2026-07-13T13:15:00Z" } | ||
| story_view { viewer: mira, story: mira_story } | ||
| story_view { viewer: mira, story: mira_story_tram } | ||
| story_view { viewer: mira, story: mira_story_market } | ||
| story_view { viewer: mira, story: priya_story } | ||
| story_view { viewer: mira, story: kenji_story } | ||
|
|
||
| // Eight current home-feed posts. Their engagement totals below are exactly | ||
| // the number of real like/comment rows, not seeded headline numbers. | ||
| lena_glaze = post { | ||
| id: "20000000-0000-4000-8000-000000000001", author: lena, | ||
| caption: "New copper-red test tiles out of the kiln. Cone 10, heavy reduction — the speckle finally behaved.", | ||
| published_at: "2026-07-13T13:00:00Z", | ||
| media_kind: "image", media_file: file("./seed/media-lena-glaze.jpg"), | ||
| media_alt: "Grid of copper-red glaze test tiles on a maple bench" } | ||
| marco_baja = post { | ||
| id: "20000000-0000-4000-8000-000000000002", author: marco, | ||
| caption: "Three days down the Baja coast. Swell arrived on the last morning, as it always does.", | ||
| published_at: "2026-07-13T10:00:00Z", media_kind: "carousel" } | ||
| nils_aurora = post { | ||
| id: "20000000-0000-4000-8000-000000000003", author: nils, | ||
| caption: "Aurora over the fjord last night — the whole sky was breathing.", | ||
| published_at: "2026-07-13T06:00:00Z", media_kind: "video", | ||
| media_file: file("./seed/media-nils-aurora-poster.jpg"), | ||
| video_file: file("./seed/media-nils-aurora.mp4"), | ||
| media_alt: "Green aurora curtains over a dark fjord" } | ||
| priya_starter = post { | ||
| id: "20000000-0000-4000-8000-000000000004", author: priya, | ||
| caption: "Day 400 of the starter. She's earned a name: Clint Yeastwood.", | ||
| published_at: "2026-07-12T23:00:00Z", media_kind: "image", | ||
| media_file: file("./seed/media-priya-starter.jpg"), | ||
| media_alt: "Open crumb of a sourdough loaf, sliced on a flour-dusted board" } | ||
| ayla_ferry = post { | ||
| id: "20000000-0000-4000-8000-000000000005", author: ayla, | ||
| caption: "Morning ferry across the Bosphorus. Tea, gulls, and nowhere to be until noon.", | ||
| published_at: "2026-07-12T16:00:00Z", media_kind: "image", | ||
| media_file: file("./seed/media-ayla-ferry.jpg"), | ||
| media_alt: "Ferry deck railing over blue water, city skyline behind" } | ||
| june_lookbook = post { | ||
| id: "20000000-0000-4000-8000-000000000006", author: june, | ||
| caption: "Studio lookbook, page one. Linen in every weight we could mill.", | ||
| published_at: "2026-07-12T10:00:00Z", media_kind: "image", | ||
| media_file: file("./seed/media-june-lookbook.jpg"), | ||
| media_alt: "Folded linen garments stacked by shade on a workbench" } | ||
| theo_court = post { | ||
| id: "20000000-0000-4000-8000-000000000007", author: theo, | ||
| caption: "Finished the mural at the 9th street court. Paint holds up better than my jumper.", | ||
| published_at: "2026-07-11T17:00:00Z", media_kind: "video", | ||
| media_file: file("./seed/media-theo-court.jpg"), | ||
| video_file: file("./seed/media-theo-court.mp4"), | ||
| media_alt: "Basketball court painted with bold geometric shapes" } | ||
| kenji_copper = post { | ||
| id: "20000000-0000-4000-8000-000000000008", author: kenji, | ||
| caption: "120km of switchbacks and one very smug goat. Copper Pass, you were worth it.", | ||
| published_at: "2026-07-11T11:00:00Z", media_kind: "image", | ||
| media_file: file("./seed/media-kenji-copper.jpg"), | ||
| media_alt: "Road bike leaning on a stone wall at a mountain pass" } | ||
|
|
||
| // Lena's and Mira's former decorative thumbnails are now genuine posts. | ||
| // They appear in profile grids and can open the same post-detail design as | ||
| // feed posts; show_in_feed keeps this history out of the compact home feed. | ||
| lena_bowls = post { id: "21000000-0000-4000-8000-000000000001", author: lena, | ||
| caption: "Copper glaze in close-up, before the wax cooled.", | ||
| published_at: "2026-07-10T14:00:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-1.jpg"), media_alt: "Copper-red glaze tiles" } | ||
| lena_greenware = post { id: "21000000-0000-4000-8000-000000000002", author: lena, | ||
| caption: "A quiet stack of bowls waiting for bisque firing.", | ||
| published_at: "2026-07-08T16:00:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-2.jpg"), media_alt: "Stack of unglazed bowls" } | ||
| lena_kiln = post { id: "21000000-0000-4000-8000-000000000003", author: lena, | ||
| caption: "Kiln Tetris, level thirty-seven.", | ||
| published_at: "2026-07-05T11:30:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-3.jpg"), media_alt: "Kiln shelf mid-load" } | ||
| lena_celadon = post { id: "21000000-0000-4000-8000-000000000004", author: lena, | ||
| caption: "Celadon tests after a slower cool-down.", | ||
| published_at: "2026-07-02T09:15:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-4.jpg"), media_alt: "Celadon test cups" } | ||
| lena_clay = post { id: "21000000-0000-4000-8000-000000000005", author: lena, | ||
| caption: "Fresh reclaim, wedged and ready for tomorrow.", | ||
| published_at: "2026-06-28T18:40:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-5.jpg"), media_alt: "Wedging table with fresh clay" } | ||
| lena_plates = post { id: "21000000-0000-4000-8000-000000000006", author: lena, | ||
| caption: "Dinner plates with just enough iron speckle.", | ||
| published_at: "2026-06-24T13:00:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-6.jpg"), media_alt: "Iron-speckled dinner plates" } | ||
| lena_throwing = post { id: "21000000-0000-4000-8000-000000000007", author: lena, | ||
| caption: "Pulling one tall cylinder before lunch.", | ||
| published_at: "2026-06-19T16:20:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-7.jpg"), media_alt: "Throwing a tall cylinder" } | ||
| lena_buckets = post { id: "21000000-0000-4000-8000-000000000008", author: lena, | ||
| caption: "Labelling day. Future me will be grateful.", | ||
| published_at: "2026-06-12T10:10:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-8.jpg"), media_alt: "Glaze buckets labelled by cone" } | ||
| lena_morning = post { id: "21000000-0000-4000-8000-000000000009", author: lena, | ||
| caption: "Seven o'clock light across the clean bench.", | ||
| published_at: "2026-06-03T14:05:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-lena-9.jpg"), media_alt: "Morning light across the studio bench" } | ||
|
|
||
| mira_pasteis = post { id: "22000000-0000-4000-8000-000000000001", author: mira, | ||
| caption: "The batch that vanished before I finished the coffee.", | ||
| published_at: "2026-07-09T07:30:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-mira-1.jpg"), media_alt: "Pastéis de nata on a marble counter" } | ||
| mira_tram = post { id: "22000000-0000-4000-8000-000000000002", author: mira, | ||
| caption: "Rails holding the first light on Rua da Conceição.", | ||
| published_at: "2026-07-04T05:45:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-mira-2.jpg"), media_alt: "Tram rails catching dawn light" } | ||
| mira_citrus = post { id: "22000000-0000-4000-8000-000000000003", author: mira, | ||
| caption: "Saturday citrus, arranged better than any still life.", | ||
| published_at: "2026-06-29T08:20:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-mira-3.jpg"), media_alt: "Market citrus stacked in crates" } | ||
| mira_tiles = post { id: "22000000-0000-4000-8000-000000000004", author: mira, | ||
| caption: "Blue after blue after blue.", | ||
| published_at: "2026-06-21T15:10:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-mira-4.jpg"), media_alt: "Tiled facade in alternating blues" } | ||
| mira_sardines = post { id: "22000000-0000-4000-8000-000000000005", author: mira, | ||
| caption: "Sardines, smoke, lemon. Nothing else needed.", | ||
| published_at: "2026-06-13T20:15:00Z", show_in_feed: false, | ||
| media_kind: "image", media_file: file("./seed/thumb-mira-5.jpg"), media_alt: "Grilled sardines over coals" } | ||
| mira_ferry = post { id: "22000000-0000-4000-8000-000000000006", author: mira, | ||
| caption: "The last ferry left a gold line all the way home.", | ||
| published_at: "2026-06-01T19:50:00Z", show_in_feed: false, | ||
| media_kind: "video", media_file: file("./seed/thumb-mira-6.jpg"), | ||
| video_file: file("./seed/media-mira-ferry.mp4"), media_alt: "Ferry wake at golden hour" } | ||
|
|
||
| // Real tag edges. Tagged grids reuse these posts and their media rather than | ||
| // carrying separate decorative thumbnails. Mira's tagged post is Marco's | ||
| // Baja carousel; its first slide is therefore her tagged-grid thumbnail. | ||
| post_tag { post: marco_baja, person: mira } | ||
| post_tag { post: june_lookbook, person: ayla } | ||
| post_tag { post: theo_court, person: june } | ||
| post_tag { post: priya_starter, person: lena } | ||
| post_tag { post: kenji_copper, person: marco } | ||
| post_tag { post: lena_glaze, person: theo } | ||
|
|
||
| // Marco's carousel, in slide order. | ||
| carousel_slide { post: marco_baja, position: 1, file: file("./seed/media-marco-baja-1.jpg"), | ||
| alt: "Long left-hand wave peeling along a desert point" } | ||
| carousel_slide { post: marco_baja, position: 2, file: file("./seed/media-marco-baja-2.jpg"), | ||
| alt: "Campfire on the bluff above the break at dusk" } | ||
| carousel_slide { post: marco_baja, position: 3, file: file("./seed/media-marco-baja-3.jpg"), | ||
| alt: "Board fins silhouetted against the sunrise" } | ||
|
|
||
| // Real comment rows. Feed cards and details count these rows. | ||
| comment { post: lena_glaze, author: kenji, created_at: "2026-07-13T13:28:00Z", | ||
| body: "That copper red is unreal. What cone are you firing to?" } | ||
| comment { post: lena_glaze, author: priya, created_at: "2026-07-13T13:35:00Z", | ||
| body: "The third tile down — that speckle! Saving this for glaze inspiration." } | ||
| comment { post: lena_glaze, author: june, created_at: "2026-07-13T13:42:00Z", | ||
| body: "Would buy the whole batch honestly. Seconds sale when?" } | ||
| comment { post: lena_glaze, author: theo, created_at: "2026-07-13T13:51:00Z", | ||
| body: "These would look wild as a court-side mosaic. Collab?" } | ||
| comment { post: marco_baja, author: kenji, created_at: "2026-07-13T10:18:00Z", | ||
| body: "That road looks nearly as good as the wave." } | ||
| comment { post: marco_baja, author: ayla, created_at: "2026-07-13T10:26:00Z", | ||
| body: "Frame two belongs on a wall." } | ||
| comment { post: nils_aurora, author: mira, created_at: "2026-07-13T06:22:00Z", | ||
| body: "The reflection makes this. Beautiful." } | ||
| comment { post: priya_starter, author: lena, created_at: "2026-07-13T12:40:00Z", | ||
| body: "Clint looks extremely healthy." } | ||
| comment { post: priya_starter, author: theo, created_at: "2026-07-13T13:05:00Z", | ||
| body: "I volunteer for quality control." } | ||
| comment { post: ayla_ferry, author: mira, created_at: "2026-07-13T06:00:00Z", | ||
| body: "That blue is perfect." } | ||
| comment { post: june_lookbook, author: ayla, created_at: "2026-07-12T22:35:00Z", | ||
| body: "The warm grey set, please." } | ||
| comment { post: theo_court, author: june, created_at: "2026-07-12T06:10:00Z", | ||
| body: "This completely changes the block." } | ||
| comment { post: kenji_copper, author: marco, created_at: "2026-07-12T00:20:00Z", | ||
| body: "Goat photo or it did not happen." } | ||
|
|
||
| // Real like edges. Mira has already liked Kenji's post; like toggles change | ||
| // the row set and therefore the displayed count with no synchronization job. | ||
| like { user: marco, post: lena_glaze } | ||
| like { user: nils, post: lena_glaze } | ||
| like { user: priya, post: lena_glaze } | ||
| like { user: ayla, post: lena_glaze } | ||
| like { user: june, post: lena_glaze } | ||
| like { user: theo, post: lena_glaze } | ||
| like { user: kenji, post: lena_glaze } | ||
| like { user: lena, post: marco_baja } | ||
| like { user: nils, post: marco_baja } | ||
| like { user: priya, post: marco_baja } | ||
| like { user: ayla, post: marco_baja } | ||
| like { user: kenji, post: marco_baja } | ||
| like { user: lena, post: nils_aurora } | ||
| like { user: marco, post: nils_aurora } | ||
| like { user: priya, post: nils_aurora } | ||
| like { user: ayla, post: nils_aurora } | ||
| like { user: june, post: nils_aurora } | ||
| like { user: lena, post: priya_starter } | ||
| like { user: marco, post: priya_starter } | ||
| like { user: nils, post: priya_starter } | ||
| like { user: ayla, post: priya_starter } | ||
| like { user: june, post: priya_starter } | ||
| like { user: theo, post: priya_starter } | ||
| like { user: kenji, post: priya_starter } | ||
| like { user: lena, post: ayla_ferry } | ||
| like { user: marco, post: ayla_ferry } | ||
| like { user: priya, post: ayla_ferry } | ||
| like { user: june, post: ayla_ferry } | ||
| like { user: lena, post: june_lookbook } | ||
| like { user: priya, post: june_lookbook } | ||
| like { user: ayla, post: june_lookbook } | ||
| like { user: theo, post: june_lookbook } | ||
| like { user: marco, post: theo_court } | ||
| like { user: ayla, post: theo_court } | ||
| like { user: june, post: theo_court } | ||
| like { user: kenji, post: theo_court } | ||
| like { user: mira, post: kenji_copper } | ||
| like { user: lena, post: kenji_copper } | ||
| like { user: marco, post: kenji_copper } | ||
| like { user: nils, post: kenji_copper } | ||
| like { user: priya, post: kenji_copper } | ||
| like { user: ayla, post: kenji_copper } | ||
| like { user: june, post: kenji_copper } | ||
| like { user: theo, post: kenji_copper } | ||
| like { user: mira, post: lena_bowls } | ||
| like { user: priya, post: lena_bowls } | ||
| like { user: june, post: lena_greenware } | ||
| like { user: theo, post: lena_kiln } | ||
| like { user: lena, post: mira_pasteis } | ||
| like { user: priya, post: mira_pasteis } | ||
| like { user: june, post: mira_tram } | ||
| like { user: kenji, post: mira_ferry } | ||
|
|
||
| // Private saved-library state. Mira's two rows make the default actor's | ||
| // Saved view useful immediately; Priya's row proves actor switching does not | ||
| // leak one person's library into another's. No public count derives from it. | ||
| save { user: mira, post: marco_baja } | ||
| save { user: mira, post: nils_aurora } | ||
| save { user: priya, post: lena_glaze } | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify every seed file referenced in app.spock exists on disk.
set -euo pipefail
grep -oP 'file\("\./seed/[^"]+"\)' examples/instagram-poc/app.spock \
| sed -E 's#file\("\./seed/([^"]+)"\)#\1#' \
| sort -u \
| while read -r name; do
if [ ! -f "examples/instagram-poc/seed/$name" ]; then
echo "MISSING: $name"
fi
doneRepository: gridaco/spock
Length of output: 162
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import re, pathlib
app = pathlib.Path("examples/instagram-poc/app.spock").read_text()
refs = sorted(set(re.findall(r'file\("\./seed/([^"]+)"\)', app)))
seed_dir = pathlib.Path("examples/instagram-poc/seed")
missing = [r for r in refs if not (seed_dir / r).is_file()]
print("refs", len(refs))
print("missing", len(missing))
for m in missing:
print(m)
PYRepository: gridaco/spock
Length of output: 171
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,200p' /tmp/coderabbit-shell-logs/shell-output-h4JOUVRepository: gridaco/spock
Length of output: 162
🏁 Script executed:
#!/bin/bash
set -euo pipefail
git ls-files examples/instagram-poc/seed | sed -n '1,200p'Repository: gridaco/spock
Length of output: 1885
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import re, pathlib
app = pathlib.Path("examples/instagram-poc/app.spock").read_text()
refs = sorted(set(re.findall(r'file\("\./seed/([^"]+)"\)', app)))
seed_dir = pathlib.Path("examples/instagram-poc/seed")
missing = [r for r in refs if not (seed_dir / r).is_file()]
print("\n".join(missing))
PYRepository: gridaco/spock
Length of output: 153
Missing seed asset reference One referenced file("./seed/…") asset is missing from examples/instagram-poc/seed/, so the seed block will fail to load until the file is added or the path is corrected.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/instagram-poc/app.spock` around lines 415 - 800, Audit every
file("./seed/...") reference in the seed block, identify the asset missing from
the examples/instagram-poc/seed collection, and either add that asset or correct
the reference to an existing file. Preserve the intended media mapping for the
associated story, post, carousel slide, or profile field, especially the story
declarations such as lena_story and mira_story.
| @@ -1 +1 @@ | |||
| Subproject commit 201e847f709738fb75d14a2b6808502cab8f6ebb | |||
| Subproject commit 120038e663544933787a28fd5b94d97947cb175f | |||
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
git submodule update --init uhura
git -C uhura cat-file -e 120038e663544933787a28fd5b94d97947cb175f^{commit}
test -d uhura
git -C uhura show --stat --oneline --no-renames 120038e663544933787a28fd5b94d97947cb175fRepository: gridaco/spock
Length of output: 6752
🏁 Script executed:
#!/bin/bash
set -eu
git ls-files 'scripts/spock-uhura.sh' 'uhura' 'web/package.json' 'examples/instagram-uhura/README.md'
printf '\n--- scripts/spock-uhura.sh ---\n'
cat -n scripts/spock-uhura.sh
printf '\n--- search for uhura artifacts/paths ---\n'
rg -n --hidden --glob '!uhura/.git' --glob '!uhura/**/.git' 'web/dist|dist/spock|canvas-chrome|spock\.js|spock\.ts|launcher|artifact|preview data|uhura.toml' .Repository: gridaco/spock
Length of output: 50369
🏁 Script executed:
#!/bin/bash
set -eu
printf '\n--- scripts/spock-uhura.sh ---\n'
cat -n scripts/spock-uhura.sh
printf '\n--- build-related mentions ---\n'
rg -n --hidden --glob '!uhura/.git' \
'web/dist|dist/spock|canvas-chrome|spock\.js|spock\.ts|uhura\.toml|preview data|launcher|artifact' \
scripts web examples README.md .github docs || trueRepository: gridaco/spock
Length of output: 15227
🏁 Script executed:
#!/bin/bash
set -eu
cd uhura
printf '\n--- exact launcher paths at 120038e ---\n'
for path in \
web/dist/play/index.html \
web/dist/play/assets \
crates/uhura-wasm/pkg/web/uhura_wasm.js \
crates/uhura-wasm/pkg/web/uhura_wasm_bg.wasm \
examples/instagram-uhura/providers/dist/spock.js \
web/dist/editor/canvas-chrome.js
do
printf '\n[%s]\n' "$path"
git ls-tree -r --name-only 120038e663544933787a28fd5b94d97947cb175f -- "$path" || true
done
printf '\n--- tree presence summary ---\n'
python3 - <<'PY'
import subprocess, sys
paths = [
"web/dist/play/index.html",
"web/dist/play/assets",
"crates/uhura-wasm/pkg/web/uhura_wasm.js",
"crates/uhura-wasm/pkg/web/uhura_wasm_bg.wasm",
"examples/instagram-uhura/providers/dist/spock.js",
"web/dist/editor/canvas-chrome.js",
]
for p in paths:
out = subprocess.check_output(
["git", "ls-tree", "-r", "--name-only", "120038e663544933787a28fd5b94d97947cb175f", "--", p],
text=True,
).strip().splitlines()
print(f"{p}: {'present' if out else 'absent'}")
PYRepository: gridaco/spock
Length of output: 905
🏁 Script executed:
#!/bin/bash
set -eu
cd uhura
printf '\n--- uhura/web/README.md (artifacts section) ---\n'
sed -n '40,80p' web/README.md
printf '\n--- uhura/Cargo.toml ---\n'
sed -n '1,40p' Cargo.toml
printf '\n--- build-wasm references ---\n'
rg -n 'build-wasm|pkg/web/uhura_wasm|checked-in web artifacts|generated artifacts are committed|clean checkout' .github README.md web/README.md scripts uhura.toml Cargo.toml examples -g '!**/dist/**' || trueRepository: gridaco/spock
Length of output: 3507
🏁 Script executed:
#!/bin/bash
set -eu
cd uhura
printf '\n--- uhura/web/README.md (artifacts section) ---\n'
sed -n '40,80p' web/README.md
printf '\n--- uhura/Cargo.toml ---\n'
sed -n '1,40p' Cargo.toml
printf '\n--- build-wasm references ---\n'
rg -n 'build-wasm|pkg/web/uhura_wasm|checked-in web artifacts|generated artifacts are committed|clean checkout' .github README.md web/README.md scripts Cargo.toml examples -g '!**/dist/**' || trueRepository: gridaco/spock
Length of output: 3456
Restore the Uhura Wasm bundle expected by scripts/spock-uhura.sh. The submodule commit is present, but uhura/crates/uhura-wasm/pkg/web/uhura_wasm.js and uhura/crates/uhura-wasm/pkg/web/uhura_wasm_bg.wasm are missing here, so a clean checkout will fail the launcher preflight until those artifacts are checked in or the launcher stops requiring them.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@uhura` at line 1, Restore and check in the generated web Wasm artifacts under
the Uhura submodule, specifically uhura_wasm.js and uhura_wasm_bg.wasm expected
by scripts/spock-uhura.sh, or update the launcher’s preflight requirement if
those artifacts are intentionally no longer needed; ensure a clean checkout
passes the launcher preflight.
Summary
uhura/maincommit5b45eaaRuntime scope
The only Spock runtime change is permissive CORS across the loopback-bound v0 development authority. This deliberately extends RFD 0015's same-origin Studio posture so a separately hosted Uhura prototype can call Spock with JSON and
X-Spock-Actorheaders. The behavior has a protocol preflight regression test.The companion Uhura language/runtime changes landed in gridaco/uhura#1. This PR's submodule gitlink now references that PR's merge commit on
uhura/main.Known limits
--spock-portdoes not rewrite the Uhura provider configuration; the project manifest must address the same port.Verification
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspacecargo run -p spock-cli -- check examples/instagram-poc/app.spockbash -n scripts/spock-uhura.shand ShellCheck